/**
 * @author Samuel Gonzalez
 * @version 1.0.6 Thu May 10, 2012 10:04PM GMT-400
 */

/*
 * Copyright (C) 2011  Samuel Gonzalez, PR
 * BenchGraph. Generates graphics and HTML tables based on HTTPERF output.
 * 
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 * 
 * In addition, as a special exception, the copyright holders give permission
 * to link the code of this work with the OpenSSL project's "OpenSSL" library
 * (or with modified versions of it that use the same license as the "OpenSSL" 
 * library), and distribute linked combinations including the two.  You must
 * obey the GNU General Public License in all respects for all of the code
 * used other than "OpenSSL".  If you modify this file, you may extend this
 * exception to your version of the file, but you are not obligated to do so.
 * If you do not wish to do so, delete this exception statement from your
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 
 */

import java.io.File;
import java.util.ArrayList;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.MissingArgumentException;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.UnrecognizedOptionException;

public class BenchGraph {
	public static void main(String[] args) {
		// Parse command line parameters
		parseParameters(args); 
	}
	
	// Start BenchGraph
	/**
	 * This method retrieves directory and filename, and display them on console.
	 * @param filename - file's name
	 * @param fileformat - file's format (type)
	 * @param exporter - where does the file come from (OLIO|HTTPERF)?
	 */
	private static void init(String filename, String fileformat, String exporter){
		String directory;
		
		int index = filename.lastIndexOf("/");
		if(index != -1){
			directory = filename.substring(0, index + 1);
			filename = filename.substring(index + 1);
		}
		else
			directory = "./";
		
		Console.wln("BenchGraph --directory=\"" +
			directory + "\"  --file=\"" + filename + "." +
			fileformat + "\"  --exporter=\"" + exporter +
			"\"\n");
		
		core(directory, filename, fileformat, exporter);	
	}
	
	/**
	 * Create two directories to contain html file and images.
	 * Verify who is the exporter and call the respectives methods
	 * @param dir - file's directory
	 * @param filename - file's name
	 * @param fileformat - file's format (type)
	 * @param exp
	 */
	private static void core(String dir, String filename, String fileformat, String exp){
		
		try {
			File topLevel = new File(dir + filename + "-statistics");
			topLevel.mkdir();

			File innerLevel = new File(topLevel + "/images");
			innerLevel.mkdir();
			
			ArrayList<String> imgNames = new ArrayList<String>();
			
			ArrayList<String> tables = new ArrayList<String>();
			if(exp.equalsIgnoreCase("HTTPERF")){
				Httperf httperf = new Httperf();
				httperf.loadFile(dir, filename, fileformat);
				Console.w("Generating HTML tables...");
				
				for(int i = 0; i < httperf.getData().size(); i++)
					tables.add(new Tables(httperf.getData().get(i)).getTable());
				Console.wln("..................................[Done]");
				
				Console.w("Generating charts...");
				for(ArrayList<String> list : httperf.getData()){
					if(list.get(0).contains("CPU") || list.get(0).contains("cpu")){
						imgNames.add(new Pie(innerLevel + "/", filename, list).getImgName());
					} else if(list.get(0).contains("Total") ||
							list.get(0).contains("total") ||
							list.get(0).contains("Connection time") ||
							list.get(0).contains("connection time") ||
							list.get(0).contains("Reply") ||
							list.get(0).contains("reply") ||
							list.get(0).contains("Errors") ||
							list.get(0).contains("errors")){
						imgNames.add(new Bar(innerLevel + "/", filename, list).getImgName());
					}
					
				}
				Console.wln(".......................................[Done]");
			}
			else if(exp.equalsIgnoreCase("OLIO")){
				Olio olio = new Olio(dir, filename, fileformat);
				olio.loadFile();
				
				Console.w("Generating HTML tables...");
				for(int i = 0; i < olio.getData().size(); i++)
					tables.add(new Tables(olio.getData().get(i)).getTable());
				Console.wln("..................................[Done]");
				
				Console.w("Generating charts...");
				for(ArrayList<String> list : olio.getData()){
					if(list.get(0).contains("Mix") ||
							list.get(0).contains("Delay Times")){
						
						list.remove(list.size() - 1); // Removes value true
						list.remove(list.size() - 1); // Removes value passed
						imgNames.add(new Bar(innerLevel + "/", filename, list).getImgName());
					} else if(list.get(0).contains("Response Times")){
						list.remove(list.size() - 3); // Removes value true
						list.remove(list.size() - 3); // Removes value passed
						imgNames.add(new Bar(innerLevel + "/", filename, list).getImgName());
					}
				}
				Console.wln(".......................................[Done]");
			}			

			// Creates HTML web page
			Console.w("Generating HTML Web page...");
			new Html(topLevel + "/" + filename + "-statistics.html", tables, "images/", imgNames);
			Console.wln("................................[Done]\nBenchGraph has successfully finished.......................... :)");
		}catch (SecurityException se) {
			Console.wln("BenchGraph is not authorize to create directories here.");
			System.exit(1);
		}catch (NullPointerException npe) {
			Console.wln("Path name is incorrect or not accesible.");
			System.exit(1);
		}
	}
	
	/**
	 * Iterates through parameters and validate them.
	 * @param args - console parameters.
	 */
	private static void parseParameters(String[] args){
		Options opts = new Options();
		
		String filename = null, fileformat = null, exporter = null;

		opts.addOption("fn", "filename", true, "REQUIRED: The name of the file to be read.");
		opts.addOption("ff", "fileformat", true, "REQUIRED: The format of the file to be read.");
		opts.addOption("e", "exporter", true, "REQUIRED: Who generated the file (HTTPERF, OLIO)?");
		
		CommandLineParser parser = new GnuParser();
		try {
			CommandLine cmd = parser.parse(opts, args);
			
			if(cmd.hasOption("filename")) // --filename & --fn
				filename = cmd.getOptionValue("filename");
			else {
				new HelpFormatter().printHelp("BenchGraph", opts);
				System.exit(1);
			}
			
			if(cmd.hasOption("fileformat")) // --fileformat & --ff
				fileformat = cmd.getOptionValue("fileformat");
			else {
				new HelpFormatter().printHelp("BenchGraph", opts);
				System.exit(1);
			}
			
			if(cmd.hasOption("exporter")){ // --exporter & --e
				exporter = cmd.getOptionValue("exporter");
				if(!exporter.equalsIgnoreCase("OLIO") && !exporter.equalsIgnoreCase("HTTPERF")){
					Console.wln("Argument provided for exporter is incorrect, must be httperf or olio.");
					System.exit(1);
				} else if(exporter.equalsIgnoreCase("OLIO") && !fileformat.equalsIgnoreCase("XML")){
					Console.wln("Olio only exports xml files at the time.");
					System.exit(1);
				}
			}
			else {
				new HelpFormatter().printHelp("BenchGraph", opts);
				System.exit(1);
			}
			
			init(filename, fileformat, exporter);
		} catch (MissingArgumentException mae) {
			Console.wln("You need to specify an argument to all parameters.\n\n");
			new HelpFormatter().printHelp("BenchGraph", opts);
			System.exit(1);
		} catch(UnrecognizedOptionException uoe){
			Console.wln("An incorrect amount of parameter was provided.\n\n");
			new HelpFormatter().printHelp("BenchGraph", opts);
			System.exit(1);
		} catch (ParseException pe) {
			Console.wln(pe.getMessage().toString());
			System.exit(1);
		}
	}
}